home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
lfs
/
lfsLoad.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-29
|
10KB
|
337 lines
/*
* lfsLoad.c --
*
* Code to handle the loading, checkpoint, and detaching of LFS file
* system.
*
* Copyright 1989 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/kernel/lfs/RCS/lfsLoad.c,v 1.8 91/05/29 14:12:37 mendel Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include <sprite.h>
#include <lfsInt.h>
#include <stdlib.h>
#include <rpc.h>
#include <string.h>
#include <lfs.h>
static Fsdm_DomainOps lfsDomainOps = {
Lfs_AttachDisk,
Lfs_DetachDisk,
Lfs_DomainWriteBack,
Lfs_RereadSummaryInfo,
Lfs_DomainInfo,
Lfs_BlockAllocate,
Lfs_GetNewFileNumber,
Lfs_FreeFileNumber,
Lfs_FileDescInit,
Lfs_FileDescFetch,
Lfs_FileDescStore,
Lfs_FileBlockRead,
Lfs_FileBlockWrite,
Lfs_FileTrunc,
Lfs_DirOpStart,
Lfs_DirOpEnd
};
/*
*----------------------------------------------------------------------
*
* LfsLoadFileSystem --
*
* Load the checkpointed state of a file system and call the LFS
* module attach routines to initialize a file system.
*
* Results:
* SUCCESS if the file system was successfully loaded.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ReturnStatus
LfsLoadFileSystem(lfsPtr, flags)
Lfs *lfsPtr; /* File system to load checkpoint state. */
int flags;
{
ReturnStatus status;
LfsCheckPointHdr checkPointHdr[2], *checkPointHdrPtr;
LfsCheckPointTrailer *trailerPtr;
LfsDiskAddr diskAddr;
int choosenOne, maxSize;
char *checkPointPtr;
int checkPointSize;
Sync_LockInitDynamic(&(lfsPtr->checkPointLock), "LfsCheckpointLock");
/*
* Examine the two checkpoint areas to locate the checkpoint area with the
* newest timestamp.
*/
LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[0],
&diskAddr);
status = LfsReadBytes(lfsPtr, diskAddr, sizeof(LfsCheckPointHdr),
(char *) (checkPointHdr+0));
if (status != SUCCESS) {
LfsError(lfsPtr, status, "Can't read checkpoint header #0");
return status;
}
LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[1],
&diskAddr);
status = LfsReadBytes(lfsPtr, diskAddr, sizeof(LfsCheckPointHdr),
(char *) (checkPointHdr+1));
if (status != SUCCESS) {
LfsError(lfsPtr, status, "Can't read checkpoint header #1");
return status;
}
choosenOne = (checkPointHdr[0].timestamp<checkPointHdr[1].timestamp) ? 1 : 0;
/*
* Read in the entire checkpoint region into a buffer.
*/
maxSize = LfsBlocksToBytes(lfsPtr,
(lfsPtr->superBlock.hdr.maxCheckPointBlocks));
checkPointPtr = malloc(maxSize);
again:
LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[choosenOne],
&diskAddr);
status = LfsReadBytes(lfsPtr, diskAddr, maxSize, checkPointPtr);
if (status != SUCCESS) {
free((char *) checkPointPtr);
LfsError(lfsPtr, status, "Can't read checkpoint region");
return status;
}
/*
* Verify checksum checkpoint region here.
*/
checkPointHdrPtr = (LfsCheckPointHdr *) checkPointPtr;
trailerPtr = (LfsCheckPointTrailer *)
(checkPointPtr + checkPointHdrPtr->size -
sizeof(LfsCheckPointTrailer));
if (checkPointHdrPtr->timestamp != trailerPtr->timestamp) {
LfsError(lfsPtr, SUCCESS, "Bad checkpoint timestamps");
choosenOne = !choosenOne;
goto again;
}
printf("LfsLoad using checkpoint area %d with timestamp %d\n",
choosenOne, checkPointHdrPtr->timestamp);
/*
* Install the domain if we can.
*/
status = Fsdm_InstallDomain(checkPointHdrPtr->domainNumber,
checkPointHdrPtr->serverID, lfsPtr->name,
flags, &(lfsPtr->domainPtr));
if (status != SUCCESS) {
free((char *) checkPointHdrPtr);
return (status);
}
lfsPtr->domainPtr->backendPtr = LfsCacheBackendInit(lfsPtr);
lfsPtr->domainPtr->domainOpsPtr = &lfsDomainOps;
lfsPtr->domainPtr->clientData = (ClientData) lfsPtr;
/*
* Read in the current stats structure.
*/
{
Lfs_StatsVersion1 *statsPtr = (Lfs_StatsVersion1 *)(trailerPtr + 1);
if (statsPtr->version != 1) {
printf("LfsLoad: Bad stats version number %d\n", statsPtr->version);
}
bcopy ((char *) statsPtr, (char *) &lfsPtr->stats,
sizeof(lfsPtr->stats));
}
checkPointPtr = checkPointPtr + sizeof(LfsCheckPointHdr);
checkPointSize = ((char *)trailerPtr) - checkPointPtr;
/*
* Process the checkpoint for each region by calling segment attach
* procedures for the modules doing segment I/O.
*/
status = LfsSegAttach(lfsPtr, checkPointPtr, checkPointSize);
if (status != SUCCESS) {
free((char *) checkPointHdrPtr);
return status;
}
/*
* Setup checkPoint data structure for next checkpoint operation. We use
* the buffer we allocated and set the nextRegion to be the one we
* didn't load from. Also set the timestamp into the future.
*/
lfsPtr->checkPoint.timestamp = checkPointHdrPtr->timestamp+1;
lfsPtr->checkPoint.nextArea = !choosenOne;
lfsPtr->checkPoint.buffer = (char *) checkPointHdrPtr;
lfsPtr->checkPoint.maxSize = maxSize;
/*
* Fill in the checkPointHdrPtr will the fields that don't change
* between checkpoints.
*/
checkPointHdrPtr->timestamp = lfsPtr->checkPoint.timestamp;
checkPointHdrPtr->size = 0;
checkPointHdrPtr->version = 1;
bzero(checkPointHdrPtr->domainPrefix,
sizeof(checkPointHdrPtr->domainPrefix));
(void)strncpy(checkPointHdrPtr->domainPrefix, lfsPtr->name,
sizeof(checkPointHdrPtr->domainPrefix)-1);
checkPointHdrPtr->domainNumber = lfsPtr->domainPtr->domainNumber;
checkPointHdrPtr->attachSeconds = Fsutil_TimeInSeconds();
checkPointHdrPtr->detachSeconds = checkPointHdrPtr->attachSeconds;
checkPointHdrPtr->serverID = rpc_SpriteID;
return status;
}
/*
*----------------------------------------------------------------------
*
* LfsDetachFileSystem --
*
* Detach a file system.
*
* Results:
* SUCCESS if the file system was successfully detach.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ReturnStatus
LfsDetachFileSystem(lfsPtr)
Lfs *lfsPtr; /* File system to load checkpoint state. */
{
ReturnStatus status;
(*lfsPtr->checkpointIntervalPtr) = 0; /* Stop the timer checkpointer. */
status = LfsCheckPointFileSystem(lfsPtr, LFS_CHECKPOINT_DETACH);
status = LfsSegDetach(lfsPtr);
free(lfsPtr->checkPoint.buffer);
return status;
}
#define LOCKPTR &lfsPtr->checkPointLock
/*
*----------------------------------------------------------------------
*
* LfsCheckPointFileSystem --
*
* Checkpoint the state of a file system by calling the LFS
* module attach routines.
*
* Results:
* SUCCESS if the file system was successfully checkpointed.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ReturnStatus
LfsCheckPointFileSystem(lfsPtr, flags)
Lfs *lfsPtr; /* File system to be checkpointed. */
int flags; /* Flags for checkpoint. */
{
LfsCheckPointHdr *checkPointHdrPtr;
int size, blocks, bytes;
LfsCheckPointTrailer *trailerPtr;
LfsDiskAddr diskAddr;
ReturnStatus status;
char *bufferPtr;
bufferPtr = lfsPtr->checkPoint.buffer;
checkPointHdrPtr = (LfsCheckPointHdr *) bufferPtr;
if (flags & LFS_CHECKPOINT_CLEANER) {
/*
* The cleaner uses it own checkpoint buffer. Allocate it
* and initialized the LfsCheckPointHdr with the values that
* don't change.
*/
bufferPtr = malloc(lfsPtr->checkPoint.maxSize);
bcopy((char *) checkPointHdrPtr, bufferPtr,
sizeof(LfsCheckPointHdr));
checkPointHdrPtr = (LfsCheckPointHdr *) bufferPtr;
}
status = LfsSegCheckPoint(lfsPtr, flags, (char *)(checkPointHdrPtr+1),
&size);
if ((status != SUCCESS) || (size < 0)) {
if (bufferPtr != lfsPtr->checkPoint.buffer) {
free(bufferPtr);
}
return status;
}
LOCK_MONITOR;
/*
* Fill in check point header and trailer.
*/
checkPointHdrPtr->timestamp = LfsGetCurrentTimestamp(lfsPtr);
checkPointHdrPtr->size = size + sizeof(LfsCheckPointHdr) +
sizeof(LfsCheckPointTrailer);
checkPointHdrPtr->version = 1;
checkPointHdrPtr->detachSeconds = Fsutil_TimeInSeconds();
trailerPtr = (LfsCheckPointTrailer *)
(bufferPtr + size + sizeof(LfsCheckPointHdr));
trailerPtr->timestamp = checkPointHdrPtr->timestamp;
trailerPtr->checkSum = 0;
/*
* Append the stats to the checkpoint regions.
*/
bytes = checkPointHdrPtr->size + sizeof(Lfs_Stats);
blocks = LfsBytesToBlocks(lfsPtr, bytes);
LFS_STATS_ADD(lfsPtr->stats.checkpoint.totalBlocks, blocks);
LFS_STATS_ADD(lfsPtr->stats.checkpoint.totalBytes, bytes);
bcopy ((char *) &lfsPtr->stats, (char *) (trailerPtr + 1),
sizeof(lfsPtr->stats));
LfsOffsetToDiskAddr(
lfsPtr->superBlock.hdr.checkPointOffset[lfsPtr->checkPoint.nextArea],
&diskAddr);
status = LfsWriteBytes(lfsPtr, diskAddr,
LfsBlocksToBytes(lfsPtr, blocks), (char *) checkPointHdrPtr);
if (status == SUCCESS) {
/*
* Set the file system up to use the other checkpoint buffer next time.
*/
lfsPtr->checkPoint.nextArea = !lfsPtr->checkPoint.nextArea;
} else {
UNLOCK_MONITOR;
LfsError(lfsPtr, status, "Can't write checkpoint region\n");
LOCK_MONITOR;
}
UNLOCK_MONITOR;
LfsSegCheckPointDone(lfsPtr, flags);
if (bufferPtr != lfsPtr->checkPoint.buffer) {
free(bufferPtr);
}
return status;
}